home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / robotparser.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  9KB  |  313 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. ''' robotparser.py
  5.  
  6.     Copyright (C) 2000  Bastian Kleineidam
  7.  
  8.     You can choose between two licenses when using this package:
  9.     1) GNU GPLv2
  10.     2) PSF license for Python 2.2
  11.  
  12.     The robots.txt Exclusion Protocol is implemented as specified in
  13.     http://info.webcrawler.com/mak/projects/robots/norobots-rfc.html
  14. '''
  15. import urlparse
  16. import urllib
  17. __all__ = [
  18.     'RobotFileParser']
  19. debug = 0
  20.  
  21. def _debug(msg):
  22.     if debug:
  23.         print msg
  24.     
  25.  
  26.  
  27. class RobotFileParser:
  28.     ''' This class provides a set of methods to read, parse and answer
  29.     questions about a single robots.txt file.
  30.  
  31.     '''
  32.     
  33.     def __init__(self, url = ''):
  34.         self.entries = []
  35.         self.default_entry = None
  36.         self.disallow_all = False
  37.         self.allow_all = False
  38.         self.set_url(url)
  39.         self.last_checked = 0
  40.  
  41.     
  42.     def mtime(self):
  43.         '''Returns the time the robots.txt file was last fetched.
  44.  
  45.         This is useful for long-running web spiders that need to
  46.         check for new robots.txt files periodically.
  47.  
  48.         '''
  49.         return self.last_checked
  50.  
  51.     
  52.     def modified(self):
  53.         '''Sets the time the robots.txt file was last fetched to the
  54.         current time.
  55.  
  56.         '''
  57.         import time as time
  58.         self.last_checked = time.time()
  59.  
  60.     
  61.     def set_url(self, url):
  62.         '''Sets the URL referring to a robots.txt file.'''
  63.         self.url = url
  64.         (self.host, self.path) = urlparse.urlparse(url)[1:3]
  65.  
  66.     
  67.     def read(self):
  68.         '''Reads the robots.txt URL and feeds it to the parser.'''
  69.         opener = URLopener()
  70.         f = opener.open(self.url)
  71.         lines = []
  72.         line = f.readline()
  73.         while line:
  74.             lines.append(line.strip())
  75.             line = f.readline()
  76.         self.errcode = opener.errcode
  77.         if self.errcode == 401 or self.errcode == 403:
  78.             self.disallow_all = True
  79.             _debug('disallow all')
  80.         elif self.errcode >= 400:
  81.             self.allow_all = True
  82.             _debug('allow all')
  83.         elif self.errcode == 200 and lines:
  84.             _debug('parse lines')
  85.             self.parse(lines)
  86.         
  87.  
  88.     
  89.     def _add_entry(self, entry):
  90.         if '*' in entry.useragents:
  91.             self.default_entry = entry
  92.         else:
  93.             self.entries.append(entry)
  94.  
  95.     
  96.     def parse(self, lines):
  97.         '''parse the input lines from a robots.txt file.
  98.            We allow that a user-agent: line is not preceded by
  99.            one or more blank lines.'''
  100.         state = 0
  101.         linenumber = 0
  102.         entry = Entry()
  103.         for line in lines:
  104.             linenumber = linenumber + 1
  105.             if not line:
  106.                 if state == 1:
  107.                     _debug('line %d: warning: you should insert allow: or disallow: directives below any user-agent: line' % linenumber)
  108.                     entry = Entry()
  109.                     state = 0
  110.                 elif state == 2:
  111.                     self._add_entry(entry)
  112.                     entry = Entry()
  113.                     state = 0
  114.                 
  115.             
  116.             i = line.find('#')
  117.             if i >= 0:
  118.                 line = line[:i]
  119.             
  120.             line = line.strip()
  121.             if not line:
  122.                 continue
  123.             
  124.             line = line.split(':', 1)
  125.             if len(line) == 2:
  126.                 line[0] = line[0].strip().lower()
  127.                 line[1] = urllib.unquote(line[1].strip())
  128.                 if line[0] == 'user-agent':
  129.                     if state == 2:
  130.                         _debug('line %d: warning: you should insert a blank line before any user-agent directive' % linenumber)
  131.                         self._add_entry(entry)
  132.                         entry = Entry()
  133.                     
  134.                     entry.useragents.append(line[1])
  135.                     state = 1
  136.                 elif line[0] == 'disallow':
  137.                     if state == 0:
  138.                         _debug('line %d: error: you must insert a user-agent: directive before this line' % linenumber)
  139.                     else:
  140.                         entry.rulelines.append(RuleLine(line[1], False))
  141.                         state = 2
  142.                 elif line[0] == 'allow':
  143.                     if state == 0:
  144.                         _debug('line %d: error: you must insert a user-agent: directive before this line' % linenumber)
  145.                     else:
  146.                         entry.rulelines.append(RuleLine(line[1], True))
  147.                 else:
  148.                     _debug('line %d: warning: unknown key %s' % (linenumber, line[0]))
  149.             line[0] == 'user-agent'
  150.             _debug('line %d: error: malformed line %s' % (linenumber, line))
  151.         
  152.         if state == 2:
  153.             self.entries.append(entry)
  154.         
  155.         _debug('Parsed rules:\n%s' % str(self))
  156.  
  157.     
  158.     def can_fetch(self, useragent, url):
  159.         '''using the parsed robots.txt decide if useragent can fetch url'''
  160.         _debug('Checking robots.txt allowance for:\n  user agent: %s\n  url: %s' % (useragent, url))
  161.         if self.disallow_all:
  162.             return False
  163.         
  164.         if self.allow_all:
  165.             return True
  166.         
  167.         if not urllib.quote(urlparse.urlparse(urllib.unquote(url))[2]):
  168.             pass
  169.         url = '/'
  170.         for entry in self.entries:
  171.             if entry.applies_to(useragent):
  172.                 return entry.allowance(url)
  173.                 continue
  174.         
  175.         if self.default_entry:
  176.             return self.default_entry.allowance(url)
  177.         
  178.         return True
  179.  
  180.     
  181.     def __str__(self):
  182.         ret = ''
  183.         for entry in self.entries:
  184.             ret = ret + str(entry) + '\n'
  185.         
  186.         return ret
  187.  
  188.  
  189.  
  190. class RuleLine:
  191.     '''A rule line is a single "Allow:" (allowance==True) or "Disallow:"
  192.        (allowance==False) followed by a path.'''
  193.     
  194.     def __init__(self, path, allowance):
  195.         if path == '' and not allowance:
  196.             allowance = True
  197.         
  198.         self.path = urllib.quote(path)
  199.         self.allowance = allowance
  200.  
  201.     
  202.     def applies_to(self, filename):
  203.         if not self.path == '*':
  204.             pass
  205.         return filename.startswith(self.path)
  206.  
  207.     
  208.     def __str__(self):
  209.         if not self.allowance or 'Allow':
  210.             pass
  211.         return 'Disallow' + ': ' + self.path
  212.  
  213.  
  214.  
  215. class Entry:
  216.     '''An entry has one or more user-agents and zero or more rulelines'''
  217.     
  218.     def __init__(self):
  219.         self.useragents = []
  220.         self.rulelines = []
  221.  
  222.     
  223.     def __str__(self):
  224.         ret = ''
  225.         for agent in self.useragents:
  226.             ret = ret + 'User-agent: ' + agent + '\n'
  227.         
  228.         for line in self.rulelines:
  229.             ret = ret + str(line) + '\n'
  230.         
  231.         return ret
  232.  
  233.     
  234.     def applies_to(self, useragent):
  235.         '''check if this entry applies to the specified agent'''
  236.         useragent = useragent.split('/')[0].lower()
  237.         for agent in self.useragents:
  238.             if agent == '*':
  239.                 return True
  240.             
  241.             agent = agent.lower()
  242.             if agent in useragent:
  243.                 return True
  244.                 continue
  245.         
  246.         return False
  247.  
  248.     
  249.     def allowance(self, filename):
  250.         '''Preconditions:
  251.         - our agent applies to this entry
  252.         - filename is URL decoded'''
  253.         for line in self.rulelines:
  254.             _debug((filename, str(line), line.allowance))
  255.             if line.applies_to(filename):
  256.                 return line.allowance
  257.                 continue
  258.         
  259.         return True
  260.  
  261.  
  262.  
  263. class URLopener(urllib.FancyURLopener):
  264.     
  265.     def __init__(self, *args):
  266.         urllib.FancyURLopener.__init__(self, *args)
  267.         self.errcode = 200
  268.  
  269.     
  270.     def http_error_default(self, url, fp, errcode, errmsg, headers):
  271.         self.errcode = errcode
  272.         return urllib.FancyURLopener.http_error_default(self, url, fp, errcode, errmsg, headers)
  273.  
  274.  
  275.  
  276. def _check(a, b):
  277.     if not b:
  278.         ac = 'access denied'
  279.     else:
  280.         ac = 'access allowed'
  281.     if a != b:
  282.         print 'failed'
  283.     else:
  284.         print 'ok (%s)' % ac
  285.     print 
  286.  
  287.  
  288. def _test():
  289.     global debug
  290.     rp = RobotFileParser()
  291.     debug = 1
  292.     rp.set_url('http://www.musi-cal.com/robots.txt')
  293.     rp.read()
  294.     _check(rp.can_fetch('*', 'http://www.musi-cal.com/'), 1)
  295.     _check(rp.can_fetch('', 'http://www.musi-cal.com/'), 0)
  296.     _check(rp.can_fetch('CherryPickerSE', 'http://www.musi-cal.com/cgi-bin/event-search?city=San+Francisco'), 0)
  297.     _check(rp.can_fetch('CherryPickerSE/1.0', 'http://www.musi-cal.com/cgi-bin/event-search?city=San+Francisco'), 0)
  298.     _check(rp.can_fetch('CherryPickerSE/1.5', 'http://www.musi-cal.com/cgi-bin/event-search?city=San+Francisco'), 0)
  299.     _check(rp.can_fetch('ExtractorPro', 'http://www.musi-cal.com/blubba'), 0)
  300.     _check(rp.can_fetch('extractorpro', 'http://www.musi-cal.com/blubba'), 0)
  301.     _check(rp.can_fetch('toolpak/1.1', 'http://www.musi-cal.com/blubba'), 0)
  302.     _check(rp.can_fetch('spam', 'http://www.musi-cal.com/search'), 0)
  303.     _check(rp.can_fetch('spam', 'http://www.musi-cal.com/Musician/me'), 1)
  304.     _check(rp.can_fetch('spam', 'http://www.musi-cal.com/'), 1)
  305.     _check(rp.can_fetch('spam', 'http://www.musi-cal.com/'), 1)
  306.     rp.set_url('http://www.lycos.com/robots.txt')
  307.     rp.read()
  308.     _check(rp.can_fetch('Mozilla', 'http://www.lycos.com/search'), 1)
  309.  
  310. if __name__ == '__main__':
  311.     _test()
  312.  
  313.